/****************************************************
[	Author:		Michael Mozdzierz
[	Date:		01/30/2014
[	File:		Math.h
[	Course:		SGD
[
****************************************************/

#pragma once
using namespace std;

namespace Math
{
	extern const float PI;

	template <typename T> 
	extern _declspec(dllexport) T Clamp(T value, T min, T max);

	// returns 'value' clamped to the 'floor' lower-bound
	template <typename T>
	extern _declspec(dllexport)  T Floor(T value, T floor);

	// returns 'value' clamped to the 'ceiling' upper-bound
	template <typename T>
	extern _declspec(dllexport) T Ceiling(T value, T ceiling);

	extern float lerp(float low, float high, float weight);

	extern _declspec(dllexport)  float to_radians(float);
	extern _declspec(dllexport)  float to_degrees(float);

	extern _declspec(dllexport)  float distance(float, float);

	extern _declspec(dllexport)  float WrapAngle(float radians);

	extern _declspec(dllexport)  int Wrap(int value, int min, int max); // wraps a given value around min and max

#undef min
#undef max
	template <typename T>
	extern _declspec(dllexport) T min(T a, T b);

	template <typename T>
	_declspec(dllexport) T max(T a, T b);

	_declspec(dllexport) bool RectContains(void* rect, void* point);
}

template <typename T>
T Math::Clamp(T value, T min, T max)
{
	if (value < min)
		return min;
	if (value > max)
		return max;

	return value;
}

template <typename T>
T Math::min(T a, T b)
{
	return a < b ? a : b;
}

template <typename T>
T Math::max(T a, T b)
{
	return a > b ? a : b;
}

template <typename T>
T Math::Floor(T value, T floor)
{
	if (value < floor)
		return floor;

	return value;
}

template <typename T>
T Math::Ceiling(T value, T ceiling)
{
	if (value > ceiling)
		return ceiling;

	return value;
}
